/*
 * Created on 13/Dez/2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package hubsniffer;

import hubsniffer.conn.HubConnection;
import hubsniffer.conn.HubInfoConnection;
import hubsniffer.db.DataBaseManager;
import hubsniffer.db.HubINFOWriter;
import hubsniffer.db.HubListReader;
import hubsniffer.db.PublicHubListGen;
import hubsniffer.db.StatisticGroupWriter;
import hubsniffer.db.StatisticWriter;
import hubsniffer.module.HublistGrabber;
import libjdc.dc.client.User;
import hubsniffer.sghdc.HubInfoPinger;
import hubsniffer.sghdc.UpdateFiles;
import hubsniffer.sghdc.tasks.AllDiferentFilesTask;
import hubsniffer.sghdc.tasks.GetFilelistTask;
import hubsniffer.sghdc.tasks.PingerTask;
import hubsniffer.sghdc.tasks.SnifferTask;
import hubsniffer.util.Host;
import libjdc.dc.log.Log;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Stack;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
/**
 * @author Daniel Botelho
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class HubSniffer {
    
    private void fetchHubInfo(long delay) throws SQLException{
        
       Iterator<DCHub> hubIt = hublist.iterator();
       Stack<ConnectHubThread> hubThreads = new Stack<ConnectHubThread>();
        
        while (hubIt.hasNext()) {
            DCHub hub = hubIt.next();
            User self =db.getSnifferUserFromHub(hub.getHub_id());
            self.setHost(Host.getHostIP());
            //if(hub.getHubLog().isIs_online()){
                hubThreads.push(new ConnectHubThread(new HubInfoConnection(hub,self),delay));
                hubThreads.peek().start();
            //}
        }
        
        while(!hubThreads.empty()){
            try {
                ConnectHubThread cht = hubThreads.pop();
                Log.out.println(hubThreads.size()+":"+cht.getHubConnection().getHub()+" Waiting..");
                cht.join();
                Log.out.println(hubThreads.size()+":"+cht.getHubConnection().getHub()+"Closed!");
                try {
                    new HubINFOWriter(db).updateHubInfo(cht.getHubConnection().getHub());
                } catch (UnsupportedEncodingException ex) {
                    ex.printStackTrace(Log.err);
                } catch (SQLException ex) {
                    ex.printStackTrace(Log.err);
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace(Log.err);
            }
        }
       
       
    }
    
          
    /**
     * 
     * @param delay 
     * @throws java.lang.ClassNotFoundException 
     * @throws java.sql.SQLException 
     */
    public static void localAccess(DataBaseManager db,long delay) throws ClassNotFoundException, SQLException{
        LinkedList<DCHub> hublist = new LinkedList<DCHub>();
        
        //long delay = 300000L;
        
        /*User self = new User("[PT]sniffer","{HubSniffer Project: http://sghdc.no-ip.org/listhubs.php} <++ V:0.674,M:A,H:1/0/0,S:3>", "DSL","admin.sghdc@gmail.com", 104219547999L);
         
        self.setHost(Host.getHostIP());*/
        
        /*
        *  Carrega a Lista de HubClients
        */
        db.getHubClients();
        
        /*
        *  Carrega a Lista de Hubs
        */
        hublist = new HubListReader(db).getHubListNacional();

        
        Log.out.println(hublist);
        
        Log.out.println("Vai come?ar");
        
        Iterator<DCHub> hubIt = hublist.iterator();
        Date start = new Date();
        
        Stack<ConnectHubThread> hubThreads = new Stack<ConnectHubThread>();
        
        while (hubIt.hasNext()) {
            DCHub hub = hubIt.next();
            User self =db.getSnifferUserFromHub(hub.getHub_id());
            self.setHost(Host.getHostIP());
            hubThreads.push(new ConnectHubThread(new HubConnection(hub,self),delay));
            hubThreads.peek().start();
        }
        
        while(!hubThreads.empty()){
            try {
                ConnectHubThread cht = hubThreads.pop();
                Log.out.println(hubThreads.size()+":"+cht.getHubConnection().getHub()+" Waiting..");
                cht.join();
                Log.out.println(hubThreads.size()+":"+cht.getHubConnection().getHub()+"Closed!");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace(Log.err);
            }
        }
        
        new StatisticWriter(start,db).commit(hublist.iterator());
        
        try {
            new HubSnifferLog(Log.out).printHubsFinal(hublist);
        } catch (IOException ex) {
            ex.printStackTrace(Log.err);
        }
        
       hubIt = hublist.iterator();
        
        while (hubIt.hasNext()) {
            DCHub hub = hubIt.next();
            User self =db.getSnifferUserFromHub(hub.getHub_id());
            self.setHost(Host.getHostIP());
            if(hub.getHubSession().isIs_online()){
                hubThreads.push(new ConnectHubThread(new HubInfoConnection(hub,self),5000));
                hubThreads.peek().start();
            }
        }
        
        while(!hubThreads.empty()){
            try {
                ConnectHubThread cht = hubThreads.pop();
                Log.out.println(hubThreads.size()+":"+cht.getHubConnection().getHub()+" Waiting..");
                cht.join();
                Log.out.println(hubThreads.size()+":"+cht.getHubConnection().getHub()+"Closed!");
                try {
                    new HubINFOWriter(db).updateHubInfo(cht.getHubConnection().getHub());
                } catch (UnsupportedEncodingException ex) {
                    ex.printStackTrace(Log.err);
                } catch (SQLException ex) {
                    ex.printStackTrace(Log.err);
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace(Log.err);
            }
        }
       
       PublicHubListGen.updateHublist();
    }
    
    private DataBaseManager db;
    private LinkedList<DCHub> hublist;
    private Date start;
    

    
     public HubSniffer(DataBaseManager db,long delay) throws ClassNotFoundException, SQLException{
       this.db = db;
        
        //Carrega a Lista de HubClients  
        this.db.getHubClients();
        
        //Carrega a Lista de Hubs
        hublist = new HubListReader(this.db).getHubListNacional();
        Log.out.println(hublist);
        
        Log.out.println("Vai come?ar");
        
        fetchHubInfo(delay);
        PublicHubListGen.updateHublist();
    }
     
     public static void SniffHub(Settings settings) throws ClassNotFoundException, SQLException{
         //LinkedList<DCHub> hublist = new LinkedList<DCHub>();
        
        DataBaseManager db = new DataBaseManager(settings.getDB_ADDRESS(), settings.getDB_USERNAME(), settings.getDB_PASSWD());
        
         db.getHubClients();
        
         //Carrega a Lista de Hubs
         //hublist = new HubListReader(db).getHubListNacional();
         //hublist = new HubListReader(db).getAllActiveHubs();
         LinkedList<DCHub> hublistNacional = new HubListReader(db).getHubListNacional();
         LinkedList<DCHub> hublistInternacional = new HubListReader(db).getHubListInternacional();
         
         Date start = new Date();
         new Killer(new SnifferTask(150000,start,db,hublistNacional,hublistInternacional),300000);
         Date end = new Date();
         
         new StatisticWriter(start,db).commit(hublistNacional.iterator(),hublistInternacional.iterator());
         
         new StatisticGroupWriter(db).commit(start,end,hublistNacional);
         
         /*new StatisticWriter(start,db).commit(hublist.iterator());
         
         new StatisticGroupWriter(db).commit(start,end,hublist);
         */
         try {
             new HubSnifferLog(Log.out).printHubsFinal(hublistNacional);
         } catch (IOException ex) {
             ex.printStackTrace(Log.err);
         }
         
         PublicHubListGen.updateHublist();
         System.exit(0);
     }
     
     public static void PingerHub() throws ClassNotFoundException, SQLException{
         LinkedList<DCHub> hublist = new LinkedList<DCHub>();
         Settings settings = Settings.getInstance();
        
        DataBaseManager db = new DataBaseManager(settings.getDB_ADDRESS(), settings.getDB_USERNAME(), settings.getDB_PASSWD());
        
         db.getHubClients();
                
         //Carrega a Lista de Hubs
         //hublist = new HubListReader(db).getHubListNacional();
         hublist = new HubListReader(db).getAllActiveHubs();
         
         Date start = new Date();
         new Killer(new PingerTask(5000,start,db,hublist),20000);
         
         PublicHubListGen.updateHublist();
         System.exit(0);
     }
     
     public static void GetFilelist() throws ClassNotFoundException, SQLException{
         LinkedList<DCHub> hublist = new LinkedList<DCHub>();
         Settings settings = Settings.getInstance();
        
        DataBaseManager db = new DataBaseManager(settings.getDB_ADDRESS(), settings.getDB_USERNAME(), settings.getDB_PASSWD());
        
         db.getHubClients();
        
         //Carrega a Lista de Hubs
         //hublist = new HubListReader(db).getHubListNacional();
         hublist = new HubListReader(db).getAllActiveHubs();
         
         Date start = new Date();
         new Killer(new GetFilelistTask(150000,start,db,hublist),300000);
         Date end = new Date();
     }
     
     public static void GetFilelist2() throws ClassNotFoundException, SQLException{
         /*Sniffer.setOutPutStream(System.out);
        Sniffer.setErrOutPutStream(System.err);*/
         LinkedList<DCHub> hublist = new LinkedList<DCHub>();
         Settings settings = Settings.getInstance();
        
        DataBaseManager db = new DataBaseManager(settings.getDB_ADDRESS(), settings.getDB_USERNAME(), settings.getDB_PASSWD());
        
         db.getHubClients();
        
         //Carrega a Lista de Hubs
         hublist = new HubListReader(db).getHubListNacional();
         Log.out.println("OLA!");
         
         Date start = new Date();
         //new Killer(new AllDiferentFilesTask(150000,start,db,hublist),300000);
         new Thread(new AllDiferentFilesTask(150000,start,db,hublist)).start();
         Date end = new Date();
     }
     

    
    /*
     *  usage: [--sniffer|--pinger|--getfiles|--files|--hublist] [OPTIONS]
     */
    public static void main(String []args) throws FileNotFoundException, ParserConfigurationException, SAXException, IOException, ClassNotFoundException, ClassNotFoundException, SQLException  {
        //System.exit(0);
            /*Sniffer.setOutPutStream(System.out);
    Sniffer.setErrOutPutStream(System.err);*/
            /*System.getProperties().setProperty("sun.jnu.encoding","ISO-8859-1");
            System.getProperties().setProperty("file.encoding","ISO-8859-1");*/
        Settings settings = Settings.getInstance();
            
            if(args[0].equalsIgnoreCase("sniffer")){
            try {
                HubSniffer.SniffHub(settings);
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace(Log.err);
            } catch (SQLException ex) {
                ex.printStackTrace(Log.err);
            }
        }else if(args[0].equalsIgnoreCase("pinger")){

            new HubInfoPinger(settings);
        }else if(args[0].equalsIgnoreCase("getfiles")){
                    try {
                        //HubSniffer.GetFilelist();
                        HubSniffer.GetFilelist2();
                    } catch (SQLException ex) {
                        ex.printStackTrace();
                    } catch (ClassNotFoundException ex) {
                        ex.printStackTrace();
                    }

        }else if(args[0].equalsIgnoreCase("files")){
                        try {

DataBaseManager db = new DataBaseManager(settings.getDB_ADDRESS(), settings.getDB_USERNAME(), settings.getDB_PASSWD());
            
                           UpdateFiles.DBUpdate(db);
                           // UpdateFiles.visitAllFiles(new File("/home/dbotelho/lists"));
                        } catch (SQLException ex) {
                            ex.printStackTrace();
                        } catch (ClassNotFoundException ex) {
                            ex.printStackTrace();
                        }
                                

 
                        
        }else if(args[0].equalsIgnoreCase("hublist")){
            try {
                //HubSniffer.HublistSniffer();
                new HublistGrabber(settings).generateHublistFiles(true);
            } catch (UnsupportedEncodingException ex) {
                ex.printStackTrace();
            } catch (SQLException ex) {
                ex.printStackTrace();
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            
        }else{
            String usage= "Usage:\n\t java HubSniffer.jar TYPE [OPITONS]\n" +
                "\nTYPE:\n" +
                "\t-s, --sniffer\t\tfaz sniff a lista de hubs\n" +
                "\t-p, --pinger\t\tfaz ping a todos os hubs\n" +
                "\t-g, --getfiles\t\tvai buscar a lista de ficheiros de todos os utilizadores\n" +
                "\t-f, --files\t\tsei la!! :P\n" +
                "\t-h, --hublist\t\tbusca todos as hublists\n" +
                "\n" +
                "OPTIONS:\n" +
                "\t-dbURL\t\taddress da BD\n" +
                "\t-dbU\t\tusername da bd\n" +
                "\t-dbP\t\tpasswd da BD\n";
        System.out.println(usage);
        }
            
    }
    
}
class Killer{
    
    public Killer(Runnable task,long delayMillis){
        Thread thread = new Thread(task);
        thread.start();
        
        // Wait for the thread to finish but don't wait longer than a
        // specified time
        try {
            thread.join(delayMillis);
        } catch (InterruptedException e) {
            // Thread was interrupted
        }
        
    }
}